package EA.testproblems;
import EA.*;

/**
This testproblem is a simple problem for initial tuning of multimodal 
optimization algorithms. <br><br>

<table border="0" cellpadding="2" cellspacing="0">
<tr bgcolor="#a0a0a0">
  <td colspan="2" valign="top"><b>Problem description</b></td>
</tr>
<tr bgcolor="#e0e0e0">
  <td valign="top" width="200"><b>Name:</b></td>
  <td valign="top">Ursem multimodal 2</td>
</tr>
<tr bgcolor="#e0e0e0">
  <td valign="top"><b>Nickname:</b></td>
  <td valign="top">&nbsp;</td>
</tr>
<tr bgcolor="#e0e0e0">
  <td valign="top"><b>Intended usage:</b></td>
  <td valign="top">Initial finetuning and tests of especially multimodal algorithms. This problem is a little harder than "Ursem multimodal 1" because the
peaks are not axis aligned or with y=0.</td>
</tr>

<tr>
  <td colspan="2" valign="top">&nbsp;</td>
</tr>
<tr bgcolor="#a0a0a0">
  <td colspan="2" valign="top"><b>Problem details</b></td>
</tr>
<tr bgcolor="#e0e0e0">
  <td valign="top"><b>Function:</b></td>
  <td valign="top">sin(2x - 0.5pi) + 3cos(y - 0.4x) + 0.5x</td>
</tr>
<tr bgcolor="#e0e0e0">
  <td valign="top"><b>Plots:</b></td>
  <td valign="top"><img src="../../images/testproblems/ursemmultimodal2.gif">&nbsp;&nbsp;
<img src="../../images/testproblems/ursemmultimodal2_contour.gif"></td>
</tr>
<tr bgcolor="#e0e0e0">
  <td valign="top"><b>Ranges:</b></td>
  <td valign="top">x = [-2.5:3.0]&nbsp;&nbsp;y = [-2.0:2.0] </td>
</tr>
<tr bgcolor="#e0e0e0">
  <td valign="top"><b>Type:</b></td>
  <td valign="top">Maximization</td>
</tr>
<tr bgcolor="#e0e0e0">
  <td valign="top"><b>No. of maximas:</b></td>
  <td valign="top">2</td>
</tr>
<tr bgcolor="#e0e0e0">
  <td valign="top"><b>No. of minimas:</b></td>
  <td valign="top">6</td>
</tr>
<tr bgcolor="#e0e0e0">
  <td valign="top"><b>Optimum radius:</b></td>
  <td valign="top">0.2
</td>
</tr>
<tr bgcolor="#e0e0e0">
  <td valign="top"><b>Optimum descriptions:</b></td>
  <td valign="top">The two maximas are located so it's harder for especially
binary encoded genomes to locate both peaks. They don't 
have the same height. The six minimas are located on the edge of the
searchspace.</td>
</tr>
<tr bgcolor="#e0e0e0">
  <td valign="top"><b>Known optimums:</b></td>
  <td valign="top">
  GMAX(1.697136454,0.6788545817),
  LMAX(-1.444456199,-0.5777824797),
  LMIN(0.1421605885,-2), 
  LMIN(-0.4210240170,2),
  LMIN(-2.5,2.0),
  LMIN(-2.5,-2.0),
  LMIN(2.738455406,2.0),
  LMIN(3.0,-2.0)
<br><font size=1>Capital letters 
means that the precise optimum is known, lowercase letters is the best known 
so far.</font></td>
</tr>
<tr>
  <td colspan="2" valign="top">&nbsp;</td>
</tr>
<tr bgcolor="#a0a0a0">
  <td colspan="2" valign="top"><b>Plotting details</b></td>
</tr>

<tr bgcolor="#e0e0e0">
  <td valign="top"><b>GNUPlot code:</b></td>
  <td valign="top">
  set hidden3d<br>
  set isosamples 50<br>
  set view 80,15<br>
  splot [-2.5:3] [-2:2] sin(2*x-0.5*pi) + 3*cos(y - 0.4*x) + 0.5*x</td>
</tr>

</table>

*/
public class UrsemMultimodal2 extends NumericalProblem
{

  // Easier way to build max
  private double[][] lmax =  {{1.697136454,0.6788545817},{-1.444456199,-0.5777824797}};
  private double[][] lmin =  {{0.1421605885,-2}, {-0.4210240170,2},{-2.5,2.0},
			      {-2.5,-2.0},{2.738455406,2.0},{3.0,-2.0}};

  public UrsemMultimodal2()
    {
      super();

      double[] optimums;

      name = "Ursem Multimodal 2";
      objectivefunction = new NumericalFitness(){
	      public double Fitness_calcFitness_inner(double[] realpos)
	      {
		  return Math.sin(2*realpos[0] - 0.5*Math.PI) + 3*Math.cos(realpos[1] - 0.4*realpos[0]) + 0.5*realpos[0];
	      };
	  };
      dimensions = 2;
      ismaximization = true;
      optimumradius = 0.2;

      intervals = new Interval[2];
      intervals[0] = new Interval(-2.5,3);
      intervals[1] = new Interval(-2,2);

      // Set up known maximas
      knownmaxima = new NumericalOptimum[lmax.length];

      for (int i=0;i<lmax.length;i++) {
	optimums = new double[dimensions];
	optimums[0] = lmax[i][0];
	optimums[1] = lmax[i][1];
	knownmaxima[i] = new NumericalOptimum(optimums, objectivefunction.calcFitness(optimums), true, false, i);
      }

      // Set up known minimas
      knownminima = new NumericalOptimum[lmin.length];

      for (int i=0;i<lmin.length;i++) {
	optimums = new double[dimensions];
	optimums[0] = lmin[i][0];
	optimums[1] = lmin[i][1];
	knownminima[i] = new NumericalOptimum(optimums, objectivefunction.calcFitness(optimums), false, false, i);
      }
    }

}
